'use strict';

const path = require("path")
const pkgDir = require("pkg-dir").sync;
const pathExists = require("path-exists").sync
const fse = require("fs-extra")

const {isObject} = require('@wf-imooc-cli-dev/utils')
const formatPath = require('@wf-imooc-cli-dev/format-path')
const npminstall = require('npminstall')
const {getDefaultRegistry,getNpmLatestVersion} = require('@wf-imooc-cli-dev/get-npm-info')


class Package {
    constructor(options) {
        if(!options) {
            throw new Error("Packge类的options参数不能为空！")
        }
        if(!isObject(options)) {
            throw new Error("Packge类的options参数必须为对象！")
        }
        // package的路径
        this.targetPath = options.targetPath
        // package的存储路径
        this.storeDir = options.storeDir
        // package的name
        this.packageName = options.packageName
        //package的version
        this.packageVersion = options.packageVersion
        //package的缓存目录前缀
        this.cacheFilePathPrefix = this.packageName.replace('/','_')

    }

    async prepare() {
        if(this.storeDir && !pathExists(this.storeDir)) {
            fse.mkdirpSync(this.storeDir)
        }
        if(this.packageVersion === 'latest') {
            this.packageVersion = await getNpmLatestVersion(this.packageName)
        }
    }

    get cacheFilePath() {
        return path.resolve(this.storeDir,`_${this
            .cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`)
    }

    getSpecificCacheFilePath(packageVersion) {
        return path.resolve(this.storeDir,`_${packageVersion}@${this.packageVersion}@${this.packageName}`)
    }

    // 判断当前Package是否存在
    async exists() {
        if(this.storeDir) {
            await this.prepare()
            return pathExists(this.cacheFilePath)
        } else {
            return pathExists(this.targetPath)
        }
    }

    // 安装packge
    async install () {
        await this.prepare()
        return npminstall({
            root:this.targetPath,
            storeDir:this.storeDir,
            registry:getDefaultRegistry(),
            pkgs:[
                {
                    name:this.packageName,
                    version:this.packageVersion
                }
            ]

        })
    }

    // 更新Package
    async update() {
        await this.prepare()
        const latestPackageVersion = await getNpmLatestVersion(this.packageName)
        const latestPackagePath = this.getSpecificCacheFilePath(latestPackageVersion)
        if(!pathExists(latestPackagePath)) {
            await npminstall({
                root:this.targetPath,
                storeDir:this.storeDir,
                registry:getDefaultRegistry(),
                pkgs:[
                    {
                        name:this.packageName,
                        version:latestPackageVersion
                    }
                ]
    
            })
            this.packageVersion = latestPackageVersion
        } else {
            this.packageVersion = latestPackageVersion
        }
    }

    getRootFilePath() {
        function _getRootFile(targetPath) {
            const dir = pkgDir(targetPath)
            if(dir) {
                const pkgFile = require(path.resolve(dir,'package.json'))
                if(pkgFile && pkgFile.main){
                    return formatPath(path.resolve(dir,pkgFile.main))
                }
            }
            
            return null
        }
        if(this.storeDir) {
            return _getRootFile(this.cacheFilePath)
        } else {
            return _getRootFile(this.targetPath)
        }
    }
}

module.exports = Package;